Version #next on the hash functions for scalars. This builds on Dave's work, extends it to T*, and changes the way double and long double are handled (no longer convert to float on 32 bit). I also picked up a minor bug with uninitialized bits on the upper end of size_t when sizeof(size_t) > sizeof(T), e.g. in hash<float>. Most of the functionality has been put in one place: __scalar_hash in <memory>. Unfortunately I could not reuse __scalar_hash for hash<long double> on x86 because of the padding bits which need to be zeroed. I didn't want to add this zeroing step to the more general __scalar_hash when it isn't needed (in the absence of padding bits). I'm not ignoring the hash<string> issue (possibly changing that to a better hash). I just haven't gotten there yet. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@145778 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/memory b/include/memory index e8abdbe..bab71b4 100644 --- a/include/memory +++ b/include/memory
@@ -2719,18 +2719,116 @@ template <class _Tp> struct hash; -template<class _Tp> -struct _LIBCPP_VISIBLE hash<_Tp*> - : public unary_function<_Tp*, size_t> +template <class _Tp, size_t = sizeof(_Tp) / sizeof(size_t)> +struct __scalar_hash; + +template <class _Tp> +struct __scalar_hash<_Tp, 0> + : public unary_function<_Tp, size_t> { _LIBCPP_INLINE_VISIBILITY - size_t operator()(_Tp* __v) const _NOEXCEPT + size_t operator()(_Tp __v) const _NOEXCEPT { - const size_t* const __p = reinterpret_cast<const size_t*>(&__v); - return *__p; + union + { + _Tp __t; + size_t __a; + } __u; + __u.__a = 0; + __u.__t = __v; + return __u.__a; } }; +template <class _Tp> +struct __scalar_hash<_Tp, 1> + : public unary_function<_Tp, size_t> +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(_Tp __v) const _NOEXCEPT + { + union + { + _Tp __t; + size_t __a; + } __u; + __u.__t = __v; + return __u.__a; + } +}; + +template <class _Tp> +struct __scalar_hash<_Tp, 2> + : public unary_function<_Tp, size_t> +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(_Tp __v) const _NOEXCEPT + { + union + { + _Tp __t; + struct + { + size_t __a; + size_t __b; + }; + } __u; + __u.__t = __v; + return __u.__a ^ __u.__b; + } +}; + +template <class _Tp> +struct __scalar_hash<_Tp, 3> + : public unary_function<_Tp, size_t> +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(_Tp __v) const _NOEXCEPT + { + union + { + _Tp __t; + struct + { + size_t __a; + size_t __b; + size_t __c; + }; + } __u; + __u.__t = __v; + return __u.__a ^ __u.__b ^ __u.__c; + } +}; + +template <class _Tp> +struct __scalar_hash<_Tp, 4> + : public unary_function<_Tp, size_t> +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(_Tp __v) const _NOEXCEPT + { + union + { + _Tp __t; + struct + { + size_t __a; + size_t __b; + size_t __c; + size_t __d; + }; + } __u; + __u.__t = __v; + return __u.__a ^ __u.__b ^ __u.__c ^ __u.__d; + } +}; + +template<class _Tp> +struct _LIBCPP_VISIBLE hash<_Tp*> + : public __scalar_hash<_Tp*> +{ +}; + template <class _Tp, class _Dp> struct _LIBCPP_VISIBLE hash<unique_ptr<_Tp, _Dp> > {